2022_coltrane_giant_steps.py

#

SPDX-FileCopyrightText: 2022 Lina El Ouali & Marin Georges SPDX-FileCopyrightText: 2024 AlICe laboratory https://alicelab.be

SPDX-License-Identifier: GPL-3.0-or-later

#

script written in blender 3.3.0 hash 0759f671cclf on windows 11 Giant Steps John Coltrane Martin Georges & Lina el Ouali 2022-2023

#

                 P R E P A R I N G   T H E   S C E N E

#

LIBRAIRIES

import bpy
import random
import math
#

CLEAN

#
Delete ALL objects and related meshes from Blender file.
The file is not saved or reopened in the process.
Select all objects and delete them from the scene.
#
def clean():
    bpy.ops.object.select_all(action="SELECT")
    bpy.ops.object.delete()
    bpy.ops.outliner.orphans_purge()


clean()
#

                 T O O L S     /     I N S E R T I N G    D A T A

radius_step = 10
current_radius = 10
number_shapes = 12
z_step = 12
for i in range(1, number_shapes):
#

-------- STEP 1: CREATING A COORDONATES NETWORK --------# Circle of fifths# Cuts the circle of fifths into 12 notes to extract coordonates, prepares for the generative figures Adds the center of the circle as a coordonate

    current_radius = i * radius_step

    bpy.ops.mesh.primitive_circle_add(
        vertices=12, scale=(1, 1, 1), radius=current_radius, location=(0, 0, 0)
    )

    coord = [
        tuple(ver.co) for ver in list(bpy.context.selected_objects[0].data.vertices)
    ]
    notes = ["C", "F", "Bb", "Eb", "Ab", "Db", "Gb", "B", "E", "A", "D", "G"]

    keys_dict = {}
#
    for co, note in zip(coord, notes):
        keys_dict[note] = co

    keys_dict["O"] = (0, 0, 0)

    print(keys_dict)
#

-------- STEP 2: SET THE 12 DIFFERENT CHORDS EXISTING IN THE CIRCLE --------# Creation of a verticles network# Creation of the 12 different shapes according to the chord played. Note: the different shape is refered to as [cord]Vert.

#
    cVert = [keys_dict["C"], keys_dict["Eb"], keys_dict["Ab"], keys_dict["D"]]
    fVert = [keys_dict["C"], keys_dict["F"], keys_dict["Ab"], keys_dict["O"]]
    bbVert = [keys_dict["D"], keys_dict["F"], keys_dict["Bb"], keys_dict["Ab"]]
    ebVert = [keys_dict["D"], keys_dict["G"], keys_dict["Bb"], keys_dict["Eb"]]
    abVert = [keys_dict["A"], keys_dict["Eb"], keys_dict["Ab"], keys_dict["Gb"]]
    dbVert = [
        keys_dict["O"],
        keys_dict["Ab"],
        keys_dict["Db"],
        keys_dict["B"],
        keys_dict["E"],
    ]
    gbVert = [keys_dict["E"], keys_dict["Bb"], keys_dict["Db"], keys_dict["Gb"]]
    bVert = [
        keys_dict["O"],
        keys_dict["Bb"],
        keys_dict["Eb"],
        keys_dict["Gb"],
        keys_dict["B"],
    ]
    eVert = [
        keys_dict["E"],
        keys_dict["D"],
        keys_dict["G"],
        keys_dict["O"],
        keys_dict["Gb"],
    ]
    aVert = [
        keys_dict["E"],
        keys_dict["A"],
        keys_dict["G"],
        keys_dict["C"],
        keys_dict["O"],
    ]
    dVert = [keys_dict["Gb"], keys_dict["A"], keys_dict["D"], keys_dict["C"]]
    gVert = [keys_dict["O"], keys_dict["Gb"], keys_dict["D"], keys_dict["G"]]
#

list of the shapes

    myFigures = [
        cVert,
        fVert,
        bbVert,
        ebVert,
        abVert,
        dbVert,
        gbVert,
        bVert,
        eVert,
        aVert,
        dVert,
        gVert,
    ]
#

-------- STEP 3: LISTS THE ALGORITHM CHOOSES FROM--------# Establishment of different sequences of the introduction part

#

-INTROS-#

    intro1 = [
        abVert,
        ebVert,
        dVert,
        gbVert,
        bVert,
        bbVert,
        dbVert,
        eVert,
        aVert,
        gVert,
        fVert,
        cVert,
    ]
    intro2 = [
        fVert,
        abVert,
        ebVert,
        gbVert,
        aVert,
        bbVert,
        gVert,
        dVert,
        dbVert,
        cVert,
        eVert,
        bVert,
    ]
    intro3 = [
        dVert,
        bbVert,
        aVert,
        cVert,
        abVert,
        gbVert,
        gVert,
        fVert,
        eVert,
        bVert,
        ebVert,
        dbVert,
    ]
    intro4 = [
        gVert,
        fVert,
        dbVert,
        aVert,
        abVert,
        bVert,
        bbVert,
        cVert,
        dVert,
        gbVert,
        ebVert,
        eVert,
    ]
#

Choosing an intro Establishment of different sequences of the solo part

    Intros = [intro1, intro2, intro3, intro4]
    myIntro = random.choice(Intros)
    print(myIntro)
#
    solo1 = [
        gVert,
        cVert,
        aVert,
        bbVert,
        fVert,
        dVert,
        bVert,
        ebVert,
        gbVert,
        eVert,
        dbVert,
        abVert,
    ]
    solo2 = [
        cVert,
        fVert,
        bbVert,
        gVert,
        gbVert,
        dbVert,
        ebVert,
        eVert,
        bVert,
        aVert,
        abVert,
        dVert,
    ]
    solo3 = [
        dVert,
        bVert,
        ebVert,
        fVert,
        gVert,
        dbVert,
        aVert,
        eVert,
        abVert,
        bbVert,
        gbVert,
        cVert,
    ]
    solo4 = [
        bbVert,
        dbVert,
        gVert,
        abVert,
        dVert,
        gVert,
        abVert,
        dVert,
        cVert,
        fVert,
        aVert,
        gbVert,
    ]
#

choosing a solo

    Solos = [solo1, solo2, solo3, solo4]
    mySolo = random.choice(Solos)
    print(mySolo)
#

                 I N T R O  :   F R A M I N G

#

-------- STEP 1: PREPARING THE PARAMETERS --------# ----VARIABLES

    radius_step = 10
    current_radius = 10
    z_step = 12
#

----FACES Defining the number of faces as the polygons have different numbers of edges

    myFacesFour = [(0, 1, 2, 3)]
    myFacesFive = [(0, 1, 2, 3, 4)]
#

-------- STEP 2: CREATE A FACE FOR THE INTRO --------#

    for note in range(0, 1):
        myVerticles = myIntro[note]
        if len(myIntro[note]) == 4:
            myFaces = myFacesFour
        else:
            myFaces = myFacesFive
            print(myFaces)
#

creation of the mesh and the object

        myMesh = bpy.data.meshes.new("polyMesh1")
        myObject = bpy.data.objects.new("poly1", myMesh)
#

link object to collection

        myCollection = bpy.context.collection
        myCollection.objects.link(myObject)
        myMesh.from_pydata(myVerticles, [], myFaces)
#

rotate mesh around the y axis

        degrees = -90
        radians = math.radians(degrees)
        myObject.rotation_euler.y = radians
#

rotate mesh around the z axis

        degrees = z_step * i
        radians = math.radians(degrees)
        myObject.rotation_euler.z = radians
#

rotate mesh around the y axis

        degrees = 50
        radians = math.radians(degrees)
        myObject.rotation_euler.x = radians
#

convert mesh into a curve

        bpy.ops.object.convert(target="CURVE")
#

                 S O L O     S A X O P H O N E

#

-------- STEP 1: PREPARING THE PARAMETERS --------# ----VARIABLES

radius_step = 10
current_radius = 10
z_step = 10
#

----FACES

myFacesFour = [(0, 1, 2, 3)]
myFacesFive = [(0, 1, 2, 3, 4)]
#

-------- STEP 2: CREATE THE FACES --------# ----VARIABLES

for note in range(0, 11):
#

SHORTCUT

    myVerticles2 = mySolo[note]
    if len(mySolo[note]) == 4:
        myFaces = myFacesFour
    else:
        myFaces = myFacesFive
        print(myFaces)
#

creation of the mesh and the object

    myMesh2 = bpy.data.meshes.new("polyMesh2")
    myObject2 = bpy.data.objects.new("poly2", myMesh2)
#

link object to collection

    myCollection = bpy.context.collection
    myCollection.objects.link(myObject2)
#

fill the mesh with the verticles information (position of verticles & connection to make face)

    myMesh2.from_pydata(myVerticles2, [], myFaces)
#

rotations

    myObject2.rotation_euler.y = math.radians(note * 30)

    current_radius = note * radius_step
    degrees = -30
    radians = math.radians(degrees)
    myObject2.rotation_euler.x = radians

    degrees = z_step * note
    radians = math.radians(degrees)
    myObject2.rotation_euler.z = radians
#

     M O D I F I E R : M A K I N G   T H E   S O L O   I N T O   G I A N T   S T E P S

get all objects as list

all_objects = list(bpy.data.objects)
#

check if objects are named poly

all_poly_objects = []
for obj in all_objects:
    if "poly2" in obj.name:
#

add polys to new list

        all_poly_objects.append(obj)
#

add and apply SOLIDIFY modifier to shapes

bpy.ops.object.select_all(action="DESELECT")
for poly in all_poly_objects:
#

Apply modifier to selected object

    poly.select_set(True)  # selected object
    bpy.context.view_layer.objects.active = poly
    bpy.ops.object.modifier_add(type="SOLIDIFY")
    bpy.context.object.modifiers["Solidify"].thickness = 4
    bpy.ops.object.modifier_apply(modifier="Solidify")
    poly.select_set(False)
#

 M O D I F I E R : T U R N I N G   T H E   I N T R O   P L A N E S   I N T O  A  F R A M E

#

check if objects are named poly

all_poly_objects = []
for obj in all_objects:
    if "poly1" in obj.name:
#

add polys to new list

        all_poly_objects.append(obj)
#

add and apply SOLIDIFY modifier to shapes

bpy.ops.object.select_all(action="DESELECT")
for poly in all_poly_objects:
#

Apply modifier to selected object

    poly.select_set(True)  # selected object
    bpy.context.view_layer.objects.active = poly
    bpy.ops.object.modifier_add(type="CURVE")
    bpy.ops.object.convert(target="CURVE")
    bpy.context.object.data.bevel_depth = 2
#

shade smooth

    bpy.ops.object.shade_smooth()